package GUI;


import java.awt.AlphaComposite;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Dimension;
import java.awt.FlowLayout;
import java.awt.Graphics;
import java.awt.Graphics2D;
import java.awt.GridLayout;
import java.awt.RenderingHints;
import java.awt.Toolkit;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;
import java.awt.event.MouseMotionListener;
import java.awt.image.BufferedImage;

import javax.imageio.ImageIO;
import javax.swing.Icon;
import javax.swing.ImageIcon;
import javax.swing.JButton;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.SwingConstants;

import GUI.Components.AndGate;
import GUI.Components.NandGate;
import GUI.Components.NorGate;
import GUI.Components.OrGate;
import GUI.Components.XNorGate;
import GUI.Components.XorGate;

import java.io.IOException;
import java.math.*;
import java.util.ArrayList;

class WorkSpacePanel extends JPanel
{
	public static PanelHolder[][] panelHolder;
	public static boolean [][]check;
	public boolean activated;
	public ArrayList<MButton> ANDGATE,ORGATE,XORGATE,XNORGATE,NANDGATE,NORGATE,NOTGATE;
	private static Icon and,or,not,xor,xnor,nand,nor;
	public BufferedImage originalImageand,resizeImageandHintPng,originalImageor,resizeImageorHintPng,originalImagenot,resizeImagenotHintPng,originalImagexor,resizeImagexorHintPng,originalImagenand,resizeImagenandHintPng,originalImagenor,resizeImagenorHintPng,originalImagexnor,resizeImagexnorHintPng;
	static int i;
	static int j;
	static int width;
	static int height;
	static boolean flag=false;
	WorkSpacePanel(int a,int b)
	{
		width=getWidth();
		height=getHeight();
		i=a;
		j=b;
		panelHolder= new PanelHolder[i][j];    
		check = new boolean[i][j];
		setLayout(new GridLayout(i,j));
		activated=false;
		panelHolder[0][0] = new PanelHolder(0,0);		
		for(int m = 0; m < i; m++) 
		{
		   for(int n = 0; n < j; n++) 
		   {
		      panelHolder[m][n] = new PanelHolder(0+(m*panelHolder[0][0].getWidth()),0+(n*panelHolder[0][0].getHeight()));
		      panelHolder[m][n].setLayout(new BorderLayout());
		      check[m][n] = false;
		      add(panelHolder[m][n]);
		   }
		}

		ANDGATE = new ArrayList<MButton>();
		NANDGATE = new ArrayList<MButton>();
		ORGATE = new ArrayList<MButton>();
		XORGATE = new ArrayList<MButton>();
		XNORGATE = new ArrayList<MButton>();
		NORGATE = new ArrayList<MButton>();
		NOTGATE = new ArrayList<MButton>();
	}
	public static void Draw(int x1,int y1,int x2,int y2)
	{
		int m1,n1,m2,n2;
		n1=(int) (x1/panelHolder[0][0].getWidth());
		m1=(int) (y1/panelHolder[0][0].getHeight());
		n2=(int) (x2/panelHolder[0][0].getWidth());
		m2=(int) (y2/panelHolder[0][0].getHeight());
		JOptionPane.showMessageDialog(null, m1+" "+n1+" "+m2+" "+n2);
		JOptionPane.showMessageDialog(null, x1+" "+y1+" "+x2+" "+y2);
		if(n1<n2&&m1!=m2)
		{
			n2--;
			panelHolder[m2][n2].SW_flag=true;
			if(m1>m2)
			{
				m1--;
				
			}
			else
			{
				m2--;
			}
		}
		else if(n1>n2&&m1!=m2)
		{
			n1--;
			panelHolder[m2][n2].NW_flag=true;
			if(m1>m2)
			{
				m1--;
			}
			else
			{
				m2--;
			}
		}
		while(true)
		{
			if(n1==n2&&flag==false)
			{
				panelHolder[m1][n1].vertical_flag=true;
				if(m1==m2)
					break;
				else if(m1<m2)
					m1++;
				else if(m1>m2)
					m1--;				
			}
			else if(m1==m2)
			{
				panelHolder[m1][n1].horizontal_flag=true;
				if(n1==n2)
					break;
				else if(n1<n2)
					n1++;
				else if(n1>n2)
					n1--;				
			}
			else
			{
				flag=true;
				if(n1<=n2)
				{
					
					if(n1==n2)
					{
						panelHolder[m1][n1].NW_flag=true;
						m1++;
						flag=false;
					}
					else if(n1<n2)
					{
						panelHolder[m1][n1].horizontal_flag=true;
						n1++;
					}
					else if(n1>n2)
					{
						panelHolder[m1][n1].horizontal_flag=true;
						n1--;
					}
				}
				else if(m1<m2)
				{
					panelHolder[m1][n1].vertical_flag=true;
					if(m1==m2)
						break;
					else if(m1<m2)
						m1++;
					else if(m1>m2)
						m1--;	
				}
			}
		}
		
		refresh();
	}
	public static void refresh()
	{
		for(int a=0;a<i;a++)
		{
			for(int b=0;b<j;b++)
			{
				if(check[a][b]==true)
				{
					panelHolder[a][b].updateUI();
				}
			}
		}
	}
	 private BufferedImage resizeImageWithHint(BufferedImage originalImage, int type)
	    {
		    	BufferedImage resizedImage = new BufferedImage(panelHolder[0][0].getWidth(),panelHolder[0][0].getHeight(),type);
		    	Graphics2D g = resizedImage.createGraphics();
		    	g.drawImage(originalImage, 0, 0, panelHolder[0][0].getWidth(),panelHolder[0][0].getHeight(), null);
		    	g.dispose();	
		    	g.setComposite(AlphaComposite.Src);
		     
		    	g.setRenderingHint(RenderingHints.KEY_INTERPOLATION,RenderingHints.VALUE_INTERPOLATION_BILINEAR);
		    	g.setRenderingHint(RenderingHints.KEY_RENDERING,RenderingHints.VALUE_RENDER_QUALITY);
		    	g.setRenderingHint(RenderingHints.KEY_ANTIALIASING,RenderingHints.VALUE_ANTIALIAS_ON);
		    
		    	return resizedImage;
	    }	
	 public static int getPanelHolderHt()
	 {
		 return panelHolder[0][0].getHeight();
	 }
	 public static int getPanelHolderWdt()
	 {
		 return panelHolder[0][0].getWidth();
	 }
	public void load_image()
	{
		try 
    	{
    		originalImageand = ImageIO.read(getClass().getResource("and.png"));
			int type = originalImageand.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImageand.getType();
			resizeImageandHintPng = resizeImageWithHint(originalImageand, type);
		} catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
		
		try 
    	{
    		originalImageor = ImageIO.read(getClass().getResource("or.png"));
			int type = originalImageor.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImageor.getType();
			resizeImageorHintPng = resizeImageWithHint(originalImageor, type);
		} catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
		
		try 
    	{
    		originalImagenand = ImageIO.read(getClass().getResource("nand.png"));
			int type = originalImagenand.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImagenand.getType();
			resizeImagenandHintPng = resizeImageWithHint(originalImagenand, type);
		} catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
		
		try 
    	{
    		originalImagenor = ImageIO.read(getClass().getResource("nor.png"));
			int type = originalImagenor.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImagenor.getType();
			resizeImagenorHintPng = resizeImageWithHint(originalImagenor, type);
		} catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
		
		try 
    	{
    		originalImagexor = ImageIO.read(getClass().getResource("xor.png"));
			int type = originalImagexor.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImagexor.getType();
			resizeImagexorHintPng = resizeImageWithHint(originalImagexor, type);
		} catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
		
		try 
    	{
    		originalImagexnor = ImageIO.read(getClass().getResource("xnor.png"));
			int type = originalImagexnor.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImagexnor.getType();
			resizeImagexnorHintPng = resizeImageWithHint(originalImagexnor, type);
		} catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
		
		try 
    	{
    		originalImagenot = ImageIO.read(getClass().getResource("not.png"));
			int type = originalImagenot.getType() == 0? BufferedImage.TYPE_INT_ARGB : originalImagenot.getType();
			resizeImagenotHintPng = resizeImageWithHint(originalImagenot, type);
		} catch (IOException e) 
		{
			JOptionPane.showMessageDialog(null, e.getMessage());
		}
		
		and = new ImageIcon( resizeImageandHintPng);
		or = new ImageIcon( resizeImageorHintPng);
		nand = new ImageIcon( resizeImagenandHintPng);
		nor = new ImageIcon( resizeImagenorHintPng);
		not = new ImageIcon( resizeImagenotHintPng);
		xnor = new ImageIcon( resizeImagexnorHintPng);
		xor = new ImageIcon( resizeImagexorHintPng);
	}
	public void flag()
	{
		if(AndGate.getFlag())
			activated=true;
		else if(OrGate.getFlag())
			activated=true;
		else if(XorGate.getFlag())
			activated=true;
		else if(NorGate.getFlag())
			activated=true;
		else if(XNorGate.getFlag())
			activated=true;
		else if(NandGate.getFlag())
			activated=true;		
	}
	
	public void paintComponent(Graphics g)
	{
		super.paintComponent(g);
		setBackground(Color.white);
		g.drawString("hi why the fuck it is not working", 200, 300);
		HandlerClass handler = new HandlerClass();
		addMouseListener(handler);
		addMouseMotionListener(handler);
	}
	private class HandlerClass implements MouseListener,MouseMotionListener
	{

		
		public void mousePressed(MouseEvent e) 
		{

		}

		public void mouseReleased(MouseEvent e) 
		{
						
		}
		public void mouseClicked(MouseEvent e) 
		{
			flag();
			load_image();
			if(activated==true)
			{
				int X = (int) Math.floor((e.getX()*j/WorkSpaceScreen.width()));
				int Y = (int) Math.floor((e.getY()*i/WorkSpaceScreen.height()));
				if(check[Y][X]!=true)
				{
					if(AndGate.getFlag())
					{
						MButton obj = new MButton(and);
						ANDGATE.add(obj);
					    //obj.setBorderPainted(false);
						panelHolder[Y][X].add(obj,BorderLayout.CENTER);
						check[Y][X]=true;
						updateUI();
						AndGate.toggleFlag();
					}						
					else if(OrGate.getFlag())
					{
						MButton obj = new MButton(or);
						ORGATE.add(obj);
					    //obj.setBorderPainted(false);
						panelHolder[Y][X].add(obj,BorderLayout.CENTER);
						check[Y][X]=true;
						updateUI();
						OrGate.toggleFlag();
					}	
					else if(XorGate.getFlag())
					{
						MButton obj = new MButton(xor);
						XORGATE.add(obj);
					    //obj.setBorderPainted(false);
						panelHolder[Y][X].add(obj,BorderLayout.CENTER);
						check[Y][X]=true;
						updateUI();
						XorGate.toggleFlag();
					}	
					else if(NorGate.getFlag())
					{
						MButton obj = new MButton(nor);
						NORGATE.add(obj);
					    //obj.setBorderPainted(false);
						panelHolder[Y][X].add(obj,BorderLayout.CENTER);
						check[Y][X]=true;
						updateUI();
						NorGate.toggleFlag();
					}	
					else if(XNorGate.getFlag())
					{
						MButton obj = new MButton(xnor);
						XNORGATE.add(obj);
					    //obj.setBorderPainted(false);
						panelHolder[Y][X].add(obj,BorderLayout.CENTER);
						check[Y][X]=true;
						updateUI();
						XNorGate.toggleFlag();
					}	
					else if(NandGate.getFlag())
					{
						MButton obj = new MButton(nand);
						NANDGATE.add(obj);
						//obj.setBorderPainted(false);
						panelHolder[Y][X].add(obj,BorderLayout.CENTER);
						check[Y][X]=true;
						updateUI();
						NandGate.toggleFlag();
					}					
				}				
			}
		}

		public void mouseEntered(MouseEvent e) 
		{
			
		}
		
		public void mouseExited(MouseEvent e) 
		{
			
		}

		public void mouseDragged(MouseEvent e) 
		{

		}

		public void mouseMoved(MouseEvent e) 
		{

		}
		
	}

}
